package base;

import java.util.ArrayList;
import java.util.Collections;

import utils.Utils;


/**
 * 
 * Population class represents a list of chromosomes.
 * 
 * The list of chromosomes are possible solutions/programs for the genetic programming algorithm.
 *
 */
public class Population {

	// list of chromosomes
	private ArrayList<Chromosome> _pop;
	
	// comparator used for comparing chromosomes
	private ChromosomeComparator _comparator;

	// get the population list
	public ArrayList<Chromosome> get_pop() {
		return _pop;
	}

	// initialize
	public Population(int maxCapacity)
	{
		_pop = new ArrayList<Chromosome>(maxCapacity);
		_comparator = new ChromosomeComparator();
	}
	
	// add chromosome to the population
	public void AddChromosome(Chromosome ch)
	{
		_pop.add(ch);
	}
		
	// remove the chromosome at the given index from the population
	public Chromosome RemoveChromosome(int index)
	{
		return _pop.remove(index);
	}
	
	// add all chromosome starting at the given index from the population
	public boolean RemoveAll(int startIndex)
	{
		return _pop.removeAll(_pop.subList(startIndex, _pop.size()-1));
	}
	
	// get the chromosome at the specified index
	public Chromosome GetChromosome(int index)
	{
		return _pop.get(index);
	}
	
	// get the best chromosome in the population according to sort implementation (by fitness)
	public Chromosome GetBestChromosome()
	{
		Chromosome ch = null;
		if (_pop.size() > 0)
		{
			Sort();
			ch = _pop.get(0);
		}
		return ch;
	}
	
	// set the population list with the given list
	public void SetChromosomesList(ArrayList<Chromosome> chroms)
	{
		_pop = chroms;
	}
	
	// calculate average fitness of the chromosomes in the population
	public double GetAvgFitness() {
		double sum = 0;
		for (Chromosome ch : _pop) 
			sum += ch.get_fitness();
		return sum/_pop.size();
	}
	
	// get the top chromosomes
	public ArrayList<Chromosome> GetTopsChromosomes(int count)
	{
		if (count >= _pop.size())
			return _pop;
					
		ArrayList<Chromosome> tops = new ArrayList<Chromosome>();
		Sort();
		for (int i = 0; i <count ; i++)
		{
			tops.add(_pop.get(i));
		}
		return tops;
	}
	
	// sort the chromosomes list according to the comparator (by fitness)
	public void Sort()
	{
		Collections.sort(_pop, _comparator);
	}
	
	// add the given list of chromosomes to the populations
	public boolean Union(Population newPopulation)
	{
		return _pop.addAll(newPopulation.get_pop());
	}
	
	// add the given list of chromosomes to the populations
	public boolean Union(ArrayList<Chromosome> chroms)
	{
		return _pop.addAll(chroms);
	}
	
	// return the size of the population
	public int Size()
	{
		return _pop.size();
	}
	
	public Chromosome GetRandomChromosome() {
		return _pop.get(Utils.rand.nextInt(_pop.size()));
	}
}
